#include "BBox.h"


BBox::BBox(float _xmin, float _ymin, float _zmin, float _xmax, float _ymax, float _zmax){
	thexmin = _xmin;
	theymin = _ymin;
	thezmin = _zmin;
	thexmax = _xmax;
	theymax = _ymax;
	thezmax = _zmax;
	theMinBound = vec3(_xmin, _ymin, _zmin);
	theMaxBound = vec3(_xmax, _ymax, _zmax);
}

BBox::BBox(vec3 min, vec3 max){
	thexmin = min.x;
	theymin = min.y;
	thezmin = min.z;
	thexmax = max.x;
	theymax = max.y;
	thezmax = max.z;
	theMinBound = min;
	theMaxBound = max;
}

BBox::BBox(){
	//make sure that any future points will definitely supercede the default values
	thexmin = 1e30f;
	theymin = 1e30f;
	thezmin = 1e30f;
	thexmax = -1e30f;
	theymax = -1e30f;
	thezmax = -1e30f;
	theMinBound = vec3(1e30f, 1e30f, 1e30f);
	theMaxBound = vec3(-1e30f, -1e30f, -1e30f);
}

BBox::BBox(BBox _a, BBox _b){
	thexmin = min(_a.xmin(), _b.xmin());
	theymin = min(_a.ymin(), _b.ymin());
	thezmin = min(_a.zmin(), _b.zmin());
	thexmax = max(_a.xmax(), _b.xmax());
	theymax = max(_a.ymax(), _b.ymax());
	thezmax = max(_a.zmax(), _b.zmax());
	theMinBound = vec3(min(_a.xmin(), _b.xmin()), min(_a.ymin(), _b.ymin()), min(_a.zmin(), _b.zmin()));
	theMaxBound = vec3(max(_a.xmax(), _b.xmax()), max(_a.ymax(), _b.ymax()), max(_a.zmax(), _b.zmax()));
}

BBox::~BBox(){
}

void BBox::addBBox(BBox _b){
	//add a BBox to the bounds
	thexmin = min(thexmin, _b.xmin());
	theymin = min(theymin, _b.ymin());
	thezmin = min(thezmin, _b.zmin());
	thexmax = max(thexmax, _b.xmax());
	theymax = max(theymax, _b.ymax());
	thezmax = max(thezmax, _b.zmax());
}

void BBox::addBBox(vec3 _min, vec3 _max){
	theMinBound = BBox::minVec(_min, theMinBound);
	theMaxBound = BBox::maxVec(_max, theMaxBound);
	thexmin = min(thexmin, _min.x);
	theymin = min(theymin, _min.y);
	thezmin = min(thezmin, _min.z);
	thexmax = max(thexmax, _max.x);
	theymax = max(theymax, _max.y);
	thezmax = max(thezmax, _max.z);
}

void BBox::addPoint(vec3 _pt){
	theMinBound = BBox::minVec(_pt, theMinBound);
	theMaxBound = BBox::maxVec(_pt, theMaxBound);
	thexmin = min(thexmin, _pt.x);
	theymin = min(theymin, _pt.y);
	thezmin = min(thezmin, _pt.z);
	thexmax = max(thexmax, _pt.x);
	theymax = max(theymax, _pt.y);
	thezmax = max(thezmax, _pt.z);
}

bool BBox::intersect(Ray *_theRay, float &_t0, float &_t1){
	//http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-7-intersecting-simple-shapes/ray-box-intersection/
	//http://people.csail.mit.edu/amy/papers/box-jgt.pdf
	/*
	float tmin, tmax, tymin, tymax, tzmin, tzmax;
	vec3 origin = _theRay->origin();
	vec3 invDir = _theRay->invDirection();
	tmin = (((invDir.x < 0) ? thexmax : thexmin) - origin.x) * invDir.x;
	tmax = (((invDir.x < 0) ? thexmin : thexmax) - origin.x) * invDir.x;
	tymin = (((invDir.y < 0) ? theymax : theymin) - origin.y) * invDir.y;
	tymax = (((invDir.y < 0) ? theymin : theymax) - origin.y) * invDir.y;
	if ((tmin > tymax) || (tymin > tmax)){
		return false;
	}
	if (tymin > tmin){
		tmin = tymin;
	}
	if (tymax < tmax){
		tmax = tymax;
	}
	tzmin = (((invDir.z < 0) ? thezmax : thezmin) - origin.z) * invDir.z;
	tzmax = (((invDir.z < 0) ? thezmin : thezmax) - origin.z) * invDir.z;
	if ((tmin > tzmax) || (tzmin > tmax)){
		return false;
	}
	if (tzmin > tmin){
		tmin = tzmin;
	}
	if (tzmax < tmax){
		tmax = tzmax;
	}
	if (tmin > _t0) _t0 = tmin;
	if (tmax < _t1) _t1 = tmax;

	return true;
	*/
	vec3 origin = _theRay->origin();
	vec3 invDir = _theRay->invDirection();
	vec3 vt0 = (theMinBound - origin) * invDir;
	vec3 vt1 = (theMaxBound - origin) * invDir;
	vec3 vtNear = BBox::minVec(vt0, vt1);
	vec3 vtFar = BBox::maxVec(vt0, vt1);
	float btMin = max(max(vtNear.x, vtNear.y), max(vtNear.x, vtNear.z));
	float btMax = min(min(vtFar.x, vtFar.y), min(vtFar.x, vtFar.z));
	_t0 = max(btMin, _t0);
	_t1 = min(btMax, _t1);
	return _t0 <= _t1;
}